package com.zq.assistant.ui.widget.recyclerview.multi;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewStub;
import android.widget.FrameLayout;

import com.zq.assistant.R;
import com.zq.assistant.ui.widget.recyclerview.RecyclerViewDivider;

import in.srain.cube.views.ptr.PtrClassicFrameLayout;
import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout;

/**
 * Created by zhangqiang on 17-4-19.
 */

public class MultiRecyclerView extends FrameLayout {

    private int progressLayoutId;
    private int emptyLayoutId;
    private int loadMoreLayoutId;
    private View progressView;
    private View emptyView;
    private View loadMoreView;
    private View contentView;
    private PtrClassicFrameLayout ptrClassicFrameLayout;
    private RecyclerView recyclerView;
    private ViewStub emptyStub;
    private ViewStub progressStub;
    private ViewStub loadMoreStub;
    private int mPaddingTop, mPaddingLeft, mPaddingRight, mPaddingBottom, mPadding;
    private boolean mClipToPadding;
    private int mDividerHeight;
    private int mDividerColor;
    private int mDividerPaddingTop, mDividerPaddingLeft, mDividerPaddingRight, mDividerPaddingBottom;
    private RecyclerViewDivider oldDivider;

    private RecyclerView.Adapter adapter;
    private boolean isLoadingMore = false;
    private boolean isPullToRefreshEnable;
    private boolean isLoadMoreEnable;
    private OnRefreshListener onRefreshListener;
    private OnLoadMoreListener onLoadMoreListener;

    private EmptyViewController emptyViewController = new DefaultEmptyViewController();

    public MultiRecyclerView(Context context) {
        super(context);
    }

    public MultiRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        LayoutInflater.from(context).inflate(R.layout.multi_recycler_view, this);
        emptyStub = (ViewStub) findViewById(R.id.layout_empty);
        progressStub = (ViewStub) findViewById(R.id.layout_progress);
        loadMoreStub = (ViewStub) findViewById(R.id.layout_load_more);
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        contentView  = findViewById(R.id.layout_content);
        ptrClassicFrameLayout = (PtrClassicFrameLayout) findViewById(R.id.ptr_classic_frame_layout);

        if (attrs != null) {

            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiRecyclerView);
            emptyLayoutId = a.getResourceId(R.styleable.MultiRecyclerView_empty_layout, R.layout.multi_default_empty);
            progressLayoutId = a.getResourceId(R.styleable.MultiRecyclerView_progress_layout, R.layout.multi_default_progress);
            loadMoreLayoutId = a.getResourceId(R.styleable.MultiRecyclerView_load_more_layout, R.layout.multi_default_load_more);
            isLoadMoreEnable = a.getBoolean(R.styleable.MultiRecyclerView_loadMore, false);
            isPullToRefreshEnable = a.getBoolean(R.styleable.MultiRecyclerView_pullToRefresh, false);
            mClipToPadding = a.getBoolean(R.styleable.MultiRecyclerView_mr_clipToPadding, false);
            mPaddingTop = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_paddingTop, 0);
            mPaddingLeft = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_paddingLeft, 0);
            mPaddingRight = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_paddingRight, 0);
            mPaddingBottom = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_paddingBottom, 0);
            mPadding = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_padding, 0);
            mDividerHeight = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_dividerHeight, 0);
            mDividerColor = a.getColor(R.styleable.MultiRecyclerView_mr_dividerColor, Color.GRAY);
            mDividerPaddingTop = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_dividerPaddingTop, 0);
            mDividerPaddingLeft = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_dividerPaddingLeft, 0);
            mDividerPaddingRight = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_dividerPaddingRight, 0);
            mDividerPaddingBottom = a.getDimensionPixelSize(R.styleable.MultiRecyclerView_mr_dividerPaddingBottom, 0);

            int ptrStyle = a.getResourceId(R.styleable.MultiRecyclerView_ptrConfig, 0);
            if (ptrStyle > 0) {

                TypedArray ptrArray = context.obtainStyledAttributes(ptrStyle, in.srain.cube.views.ptr.R.styleable.PtrFrameLayout);
                ptrClassicFrameLayout.setResistance(ptrArray.getFloat(in.srain.cube.views.ptr.R.styleable.PtrFrameLayout_ptr_resistance, 1.7f));
                ptrClassicFrameLayout.setKeepHeaderWhenRefresh(ptrArray.getBoolean(in.srain.cube.views.ptr.R.styleable.PtrFrameLayout_ptr_keep_header_when_refresh, true));
                ptrArray.recycle();
            }
            a.recycle();
        }

        showProgress();

        recyclerView.setClipToPadding(mClipToPadding);
        if (mPadding > 0) {
            recyclerView.setPadding(mPadding, mPadding, mPadding, mPadding);
        } else {
            recyclerView.setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);
        }
        recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
        RecyclerView.ItemAnimator itemAnimator = recyclerView.getItemAnimator();
        if (itemAnimator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
        }
        recyclerView.addOnScrollListener(internalScrollerListener);
        ptrClassicFrameLayout.setEnabled(isPullToRefreshEnable);
        ptrClassicFrameLayout.setPtrHandler(new PtrDefaultHandler() {
            @Override
            public void onRefreshBegin(PtrFrameLayout frame) {

                if (onRefreshListener != null) {
                    onRefreshListener.onRefresh(MultiRecyclerView.this);
                }
            }

            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                return PtrDefaultHandler.checkContentCanBePulledDown(frame, recyclerView, header);
            }
        });
    }

    public void setAdapter(RecyclerView.Adapter adapter) {

        hideProgress();

        if (this.adapter != null) {
            this.adapter.unregisterAdapterDataObserver(observer);
        }

        this.adapter = adapter;
        recyclerView.setAdapter(adapter);
        if (adapter != null) {
            adapter.registerAdapterDataObserver(observer);
        }

        if (emptyViewController != null && emptyViewController.shouldShowEmptyView(this)) {

            showEmpty();
            hideContentView();
        } else {

            hideEmpty();
            showContentView();
        }
    }

    private RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            update();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            update();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            super.onItemRangeChanged(positionStart, itemCount, payload);
            update();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            update();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            update();
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            super.onItemRangeMoved(fromPosition, toPosition, itemCount);
            update();
        }
    };

    private void update() {

        hideProgress();
        if (emptyViewController != null && emptyViewController.shouldShowEmptyView(this)) {

            showEmpty();
            hideContentView();
        } else {

            hideEmpty();
            showContentView();
        }
    }

    private RecyclerView.OnScrollListener internalScrollerListener = new RecyclerView.OnScrollListener() {

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            if (isLoadingMore || !isLoadMoreEnable || dy <= 0) {
                return;
            }

            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

            int lastVisibleItem = findLastVisibleItem(layoutManager);
            int totalItemCount = layoutManager.getItemCount();
            int visibleItemCount = layoutManager.getChildCount();

            if (totalItemCount - lastVisibleItem == 1 && totalItemCount > visibleItemCount) {

                View childView = recyclerView.getChildAt(visibleItemCount - 1);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
                if (childView.getBottom() + layoutParams.bottomMargin > recyclerView.getBottom() - recyclerView.getPaddingBottom()) {
                    return;
                }

                isLoadingMore = true;
                showLoadMore();
                if (onLoadMoreListener != null) {
                    onLoadMoreListener.onLoadMore(MultiRecyclerView.this);
                }
            }
        }
    };


    public void refreshComplete() {

        ptrClassicFrameLayout.refreshComplete();
    }

    public void loadMoreComplete() {

        isLoadingMore = false;
        hideLoadMore();
    }

    public RecyclerView.Adapter getAdapter() {

        return this.adapter;
    }

    public void smoothScrollBy(int dx, int dy) {

        recyclerView.smoothScrollBy(dx, dy);
    }

    public void addOnScrollListener(RecyclerView.OnScrollListener onScrollListener) {

        recyclerView.addOnScrollListener(onScrollListener);
    }

    public void scrollToPosition(int position) {

        recyclerView.scrollToPosition(position);
    }

    public RecyclerView getRecyclerView() {
        return recyclerView;
    }

    public int findFirstVisiblePosition() {

        return findFirstVisibleItem(recyclerView.getLayoutManager());
    }

    public int findLastVisiblePosition() {

        return findLastVisibleItem(recyclerView.getLayoutManager());
    }

    public interface OnRefreshListener {

        void onRefresh(MultiRecyclerView multiRecyclerView);
    }

    public interface OnLoadMoreListener {

        void onLoadMore(MultiRecyclerView multiRecyclerView);
    }

    private int findLastVisibleItem(RecyclerView.LayoutManager layoutManager) {

        if (layoutManager instanceof LinearLayoutManager) {

            return ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {

            int[] info = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
            ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(info);
            return findMax(info);
        } else {

            throw new IllegalArgumentException("unSupport layoutManager : " + layoutManager);
        }
    }

    private int findFirstVisibleItem(RecyclerView.LayoutManager layoutManager) {

        if (layoutManager instanceof LinearLayoutManager) {

            return ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {

            int[] info = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
            ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(info);
            return findMin(info);
        } else {

            throw new IllegalArgumentException("unSupport layoutManager : " + layoutManager);
        }
    }

    private int findMax(int[] positions) {

        int max = Integer.MIN_VALUE;
        for (int a :
                positions) {

            if (a > max) {
                max = a;
            }
        }
        return max;
    }

    private int findMin(int[] positions) {

        int min = Integer.MAX_VALUE;
        for (int a :
                positions) {

            if (a < min) {
                min = a;
            }
        }
        return min;
    }

    public void setLayoutManager(RecyclerView.LayoutManager layoutManager) {

        if (mDividerHeight > 0 && layoutManager instanceof LinearLayoutManager) {

            if (oldDivider != null) {
                recyclerView.removeItemDecoration(oldDivider);
            }

            int orientation = ((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL ? LinearLayoutManager.VERTICAL : LinearLayoutManager.HORIZONTAL;
            RecyclerViewDivider divider = new RecyclerViewDivider(orientation, mDividerHeight, mDividerColor);
            divider.setPaddingLeft(mDividerPaddingLeft);
            divider.setPaddingRight(mDividerPaddingRight);
            divider.setPaddingTop(mDividerPaddingTop);
            divider.setPaddingBottom(mDividerPaddingBottom);
            recyclerView.addItemDecoration(divider);
            oldDivider = divider;
        }
        recyclerView.setLayoutManager(layoutManager);
    }

    public void addItemDecoration(RecyclerView.ItemDecoration itemDecoration) {

        recyclerView.addItemDecoration(itemDecoration);
    }


    public void showEmpty() {

        inflateEmptyView();
        emptyStub.setVisibility(View.VISIBLE);
    }

    public void hideEmpty() {

        emptyStub.setVisibility(View.GONE);
    }

    public void showProgress() {

        inflateProgressView();
        progressStub.setVisibility(View.VISIBLE);

        setEnabled(false);
    }

    public void hideProgress() {

        progressStub.setVisibility(View.GONE);
        setEnabled(true);
    }

    public void showLoadMore() {

        inflateLoadMoreView();
        loadMoreStub.setVisibility(View.VISIBLE);
        recyclerView.scrollTo(0,0);
    }

    public RecyclerView.LayoutManager getLayoutManager(){
        return recyclerView.getLayoutManager();
    }

    public void hideLoadMore() {

        loadMoreStub.setVisibility(View.GONE);
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }

    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        this.onRefreshListener = onRefreshListener;
    }

    public View getRecyclerViewChildAt(int index) {
        return recyclerView.getChildAt(index);
    }

    public View getProgressView() {

        inflateProgressView();
        return progressView;
    }

    public View getEmptyView() {

        inflateEmptyView();
        return emptyView;
    }

    public View getLoadMoreView() {

        inflateLoadMoreView();
        return loadMoreView;
    }

    public void showContentView(){

        contentView.setVisibility(View.VISIBLE);
    }

    public void hideContentView(){

        contentView.setVisibility(View.INVISIBLE);
    }

    /**
     * 解析空view
     */
    private void inflateEmptyView() {

        if (emptyLayoutId > 0 && emptyView == null) {

            emptyStub.setLayoutResource(emptyLayoutId);
            emptyView = emptyStub.inflate();
        }
    }

    /**
     * 解析Loading view
     */
    private void inflateProgressView() {

        if (progressLayoutId > 0 && progressView == null) {

            progressStub.setLayoutResource(progressLayoutId);
            progressView = progressStub.inflate();
        }
    }

    /**
     * 解析加载更多view
     */
    private void inflateLoadMoreView() {

        if (loadMoreLayoutId > 0 && loadMoreView == null) {

            loadMoreStub.setLayoutResource(loadMoreLayoutId);
            loadMoreView = loadMoreStub.inflate();
        }
    }

    /**
     * 空view控制器
     */
    public interface EmptyViewController{

        boolean shouldShowEmptyView(MultiRecyclerView recyclerView);
    }

    /**
     * 默认的空view控制器
     */
    public static class DefaultEmptyViewController implements EmptyViewController{

        @Override
        public boolean shouldShowEmptyView(MultiRecyclerView recyclerView) {

            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            return adapter == null || adapter.getItemCount() <= 0;
        }
    }

    /**
     * 设置空view控制器
     * @param emptyViewController
     */
    public void setEmptyViewController(EmptyViewController emptyViewController) {

        if(emptyViewController == null){
            return;
        }
        this.emptyViewController = emptyViewController;
    }

}
